/*
 * main.cpp
 *
 *  Created on: 23.07.2013
 *      Author: Roma Jam
 */

#include "ch.h"
#include "hal.h"

#include "kl_lib_f4xx.h"
#include "tim_F4xx.h"
#include "clocking_F40x.h"
#include "cmd_uart.h"

#define DAC_DMA             STM32_DMA1_STREAM5
#define DAC_DMA_MODE        STM32_DMA_CR_CHSEL(7) | \
                            DMA_PRIORITY_LOW | \
                            STM32_DMA_CR_MSIZE_HWORD | \
                            STM32_DMA_CR_PSIZE_HWORD | \
                            STM32_DMA_CR_CIRC  |      \
                            STM32_DMA_CR_MINC |       /* Memory pointer increase */ \
                            STM32_DMA_CR_DIR_M2P      /* Direction is memory to peripheral */
//                            STM32_DMA_CR_TCIE      /* Enable Transmission Int C */

const uint16_t Sine12bit[32] = {
                      2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
                      3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
                      599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};


static inline void Init();
void ThreadTask();

static WORKING_AREA(waThdTask, 128);
static msg_t ThdTask(void *arg) {
    (void)arg;
    chRegSetThreadName("Task");
    while(1) ThreadTask();
    return 0;
}

uint8_t i;
// Application entry point
int main(void) {
	// ======= Setup Clock and Core Vcc ======
    Voltage.SetupVcc(Vcc2V7_3V6);
    Clk.SetupFlashLatency(24);
    uint8_t ClkResult = 1;
    // HSE 8 Mhz/4 = 2 MHz, 2*192 = 384 MHz, 384/8 = 48 PreAHB, 384/8 = 48 UsbFreq
    Clk.SetupPLLDividers(4, 192, pllSysDiv8, 8);
    // Bus dividers
    Clk.SetupBusDividers(ahbDiv2, apbDiv1, apbDiv1);
    if((ClkResult = Clk.SwitchToPLL()) == 0) {
        Clk.HSIDisable();
    }
    Clk.UpdateFreqValues();

    // ==== Init OS ====
    halInit();
    chSysInit();
    // ==== Init Hard & Soft ====
    Init();
    if(ClkResult) Uart.Printf("Clock failure\r");
    // Init Thread
    chThdCreateStatic(waThdTask, sizeof(waThdTask), NORMALPRIO, ThdTask, NULL);


    rccEnableAPB1(RCC_APB1ENR_DACEN, FALSE);    // Enable Rcc
    PinSetupAnalog(GPIOA, 4, pudNone);          // GPIO

    Tmr.Init(TIM6);
    Tmr.SetTopValue(255);
    Tmr.MasterModeSelect(mmUpdate);
    Tmr.DmaOnTriggerEnable();
    Tmr.Enable();

    // ==== DMA ====
    rccEnableDMA1(FALSE);
    dmaStreamAllocate(DAC_DMA, IRQ_PRIO_MEDIUM, NULL, NULL);
    dmaStreamSetPeripheral(DAC_DMA, &DAC->DHR12R1);
    dmaStreamSetMode      (DAC_DMA, DAC_DMA_MODE);
    dmaStreamSetMemory0(DAC_DMA, Sine12bit);
    dmaStreamSetTransactionSize(DAC_DMA, 32);
    dmaStreamSetMode(DAC_DMA, DAC_DMA_MODE);
    dmaStreamEnable(DAC_DMA);

    DAC->CR = 0;
    DAC->CR |= DAC_CR_BOFF1;                    // OutPutBuffer Enable
    DAC->CR |= DAC_CR_DMAEN1;                   // Enable DMA
    DAC->CR |= DAC_CR_TEN1;
    DAC->CR |= DAC_CR_EN1;


    PinSetupOut(GPIOD, 12, omPushPull, pudPullUp, ps100MHz); // 12 - Green
//    PinSetupOut(GPIOD, 13, omPushPull, pudPullUp, ps100MHz); // 13 - Orange
//    PinSetupOut(GPIOD, 14, omPushPull, pudPullUp, ps100MHz); // 14 - Red
//    PinSetupOut(GPIOD, 15, omPushPull, pudPullUp, ps100MHz); // 15 - Blue

    while(TRUE) {
        chThdSleepMilliseconds(450);
	}
}

void ThreadTask() {
	PinToggle(GPIOD, 12);
//	Uart.Printf("a");
	chThdSleepMilliseconds(251);
}

void Init() {
    Uart.Init(57600);
    Uart.Printf("\rDrone AHB=%u; APB1=%u; APB2=%u\r", Clk.AHBFreqHz, Clk.APB1FreqHz, Clk.APB2FreqHz);
}
